import React, { useContext } from "react";
import getConfig from "next/config";
import { useRouter } from "next/router";
import { useCookies } from "react-cookie";
import jwt from "jsonwebtoken";
import { ThemeContext } from "styled-components";
import { transparentize } from "polished";
import SEO from "../components/SEO";
import Text from "../components/Text";
import Input from "../components/Input";
import Button from "../components/Button";
import Box from "../components/Box";
import { NotificationContext } from "../components/Notifications";
import LoadingContext from "../utils/LoadingContext";
import LocaleContext from "../utils/LocaleContext";

export const usernamePattern = "[A-Za-z0-9.]+";

const Register = ({ token: inviteToken, tokenError }) => {
  const [, setCookie] = useCookies();

  const { colors } = useContext(ThemeContext);
  const { addNotification } = useContext(NotificationContext);
  const { setLoading } = useContext(LoadingContext);
  const { getLocaleString } = useContext(LocaleContext);

  const router = useRouter();

  const {
    publicRuntimeConfig: { SQ_API_URL, SQ_ALLOW_REGISTER },
  } = getConfig();

  const handleRegister = async (e) => {
    e.preventDefault();
    setLoading(true);
    const form = new FormData(e.target);

    try {
      const res = await fetch(`${SQ_API_URL}/register`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          email: form.get("email"),
          username: form.get("username"),
          password: form.get("password"),
          invite: inviteToken,
        }),
      });

      if (res.status !== 200) {
        const reason = await res.text();
        throw new Error(reason);
      }

      const { token, uid, username } = await res.json();

      const expires = new Date();
      expires.setTime(expires.getTime() + 60 * 60 * 24 * 14 * 1000); // 14 days
      setCookie("token", token, { path: "/", expires });
      setCookie("userId", uid, { path: "/", expires });
      setCookie("username", username, { path: "/", expires });

      addNotification(
        "success",
        `${getLocaleString("welcome")} ${form.get("username")}!`
      );

      router.push("/?newUser=true");
    } catch (e) {
      addNotification(
        "error",
        `${getLocaleString("registerFailed")}: ${e.message}`
      );
      console.error(e);
    }

    setLoading(false);
  };

  if (SQ_ALLOW_REGISTER !== "open" && SQ_ALLOW_REGISTER !== "invite") {
    return (
      <>
        <SEO title={getLocaleString("register")} />
        <Box
          display="flex"
          alignItems="center"
          justifyContent="center"
          minHeight="calc(100vh - 140px)"
          py={6}
        >
          <Box
            width="100%"
            maxWidth="400px"
            bg="sidebar"
            borderRadius={2}
            border="1px solid"
            borderColor="border"
            p={6}
            _css={{
              boxShadow: "0 8px 32px rgba(0, 0, 0, 0.1)",
            }}
          >
            <Box textAlign="center" mb={6}>
              <Text as="h1" fontSize={4} fontWeight="600" mb={2} color="text">
                {getLocaleString("register")}
              </Text>
              <Text color="grey" fontSize={1}>
                Registration is currently closed
              </Text>
            </Box>
            <Text textAlign="center" color="grey">
              {getLocaleString("registrationClosed")}.
            </Text>
          </Box>
        </Box>
      </>
    );
  }

  return (
    <>
      <SEO title={getLocaleString("register")} />
      <Box
        display="flex"
        alignItems="center"
        justifyContent="center"
        minHeight="calc(100vh - 140px)"
        py={6}
      >
        <Box
          width="100%"
          maxWidth="400px"
          bg="sidebar"
          borderRadius={2}
          border="1px solid"
          borderColor="border"
          p={6}
          _css={{
            boxShadow: "0 8px 32px rgba(0, 0, 0, 0.1)",
          }}
        >
          <Box textAlign="center" mb={6}>
            <Text as="h1" fontSize={4} fontWeight="600" mb={2} color="text">
              {getLocaleString("register")}
            </Text>
            <Text color="grey" fontSize={1}>
              Create your new account
            </Text>
          </Box>

          {!tokenError ? (
            <Box as="form" onSubmit={handleRegister}>
              <Input
                name="email"
                type="email"
                label={getLocaleString("email")}
                mb={4}
                required
                _css={{
                  transition: "all 0.2s ease",
                  "&:focus": {
                    borderColor: "primary",
                    boxShadow: "0 0 0 3px rgba(244, 93, 72, 0.1)",
                  },
                }}
              />

              <Input
                name="username"
                label={getLocaleString("username")}
                placeholder={getLocaleString("usernameRules")}
                pattern={usernamePattern}
                mb={4}
                required
                _css={{
                  transition: "all 0.2s ease",
                  "&:focus": {
                    borderColor: "primary",
                    boxShadow: "0 0 0 3px rgba(244, 93, 72, 0.1)",
                  },
                }}
              />

              <Input
                name="password"
                type="password"
                label={getLocaleString("password")}
                mb={4}
                required
                _css={{
                  transition: "all 0.2s ease",
                  "&:focus": {
                    borderColor: "primary",
                    boxShadow: "0 0 0 3px rgba(244, 93, 72, 0.1)",
                  },
                }}
              />

              <Button
                width="100%"
                py={3}
                fontSize={2}
                fontWeight="500"
                _css={{
                  background: "linear-gradient(135deg, #000, #ff6b4a)",
                  border: "none",
                  transition: "all 0.3s ease",
                  "&:hover": {
                    background: "linear-gradient(135deg, #e54d38, #000)",
                    transform: "translateY(-1px)",
                    boxShadow: "0 4px 12px rgba(244, 93, 72, 0.3)",
                  },
                  "&:active": {
                    transform: "translateY(0)",
                  },
                }}
              >
                {getLocaleString("register")}
              </Button>
            </Box>
          ) : (
            <Box
              bg={transparentize(0.8, colors.error)}
              border="1px solid"
              borderColor="error"
              borderRadius={1}
              p={4}
              _css={{
                boxShadow: "0 4px 12px rgba(255, 51, 51, 0.1)",
              }}
            >
              <Text textAlign="center" color="error" fontWeight="500">
                {getLocaleString("registerFailed")}: {tokenError}
              </Text>
            </Box>
          )}
        </Box>
      </Box>
    </>
  );
};

export const getServerSideProps = async ({ query: { token } }) => {
  const {
    serverRuntimeConfig: { SQ_JWT_SECRET, SQ_ALLOW_REGISTER },
  } = getConfig();
  if (SQ_ALLOW_REGISTER === "open") return { props: {} };
  if (!token && SQ_ALLOW_REGISTER === "invite")
    return { props: { tokenError: "Invite token not provided" } };
  try {
    const decoded = await jwt.verify(token, SQ_JWT_SECRET);
    if (decoded.validUntil < Date.now())
      return { props: { tokenError: "Invite has expired" } };
    return { props: { token } };
  } catch (e) {
    return { props: { tokenError: e.message } };
  }
};

export default Register;
